﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

using ServiceStack.Redis;

namespace Seven.NoSql.Redis
{
    public class RedisRepository
    {
        private RedisClient _Client;
        private RedisClient Client { get { if (this._Client == null) { _Client = new RedisClient(Config.RedisServerIP, Config.RedisServerPort); } return this._Client; } }

        /// <summary>
        /// 往指定list中添加项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <param name="value">项值</param>
        public void AddItemToList(string listId, string value)
        {
            this.Client.AddItemToList(listId, value);
        }

        /// <summary>
        /// 往指定list中添加项集合
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <param name="values">项值集合</param>
        public void AddRangeToList(string listId, List<string> values)
        {
            this.Client.AddRangeToList(listId, values);
        }

        /// <summary>
        /// 获取指定list中的所有项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <returns></returns>
        public List<string> GetAllItemsFromList(string listId)
        {
            return this.Client.GetAllItemsFromList(listId);
        }

        /// <summary>
        /// 获取指定list中指定索引的项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <param name="listIndex">项索引</param>
        /// <returns></returns>
        public string GetItemFromList(string listId, int listIndex)
        {
            return this.Client.GetItemFromList(listId, listIndex);
        }

        /// <summary>
        /// 获取指定list中的项数量
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <returns></returns>
        public long GetListCount(string listId)
        {
            return this.Client.GetListCount(listId);
        }

        /// <summary>
        /// 移除指定list中的所有项
        /// </summary>
        /// <param name="listId">指定list</param>
        public void RemoveAllFromList(string listId)
        {
            this.Client.RemoveAllFromList(listId);
        }

        /// <summary>
        /// 移除指定list中的第一项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <returns></returns>
        public string RemoveStartFromList(string listId)
        {
            return this.Client.RemoveStartFromList(listId);
        }

        /// <summary>
        /// 移除指定list中的最后一项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <returns></returns>
        public string RemoveEndFromList(string listId)
        {
            return this.Client.RemoveEndFromList(listId);
        }

        /// <summary>
        /// 移除指定list中的指定值的项
        /// </summary>
        /// <param name="listId">指定list</param>
        /// <param name="value">要移除的项的值</param>
        /// <returns></returns>
        public long RemoveItemFromList(string listId, string value)
        {
            return this.Client.RemoveItemFromList(listId, value);
        }

        /// <summary>
        /// 设置一个键值数据
        /// </summary>
        /// <typeparam name="T">值类型</typeparam>
        /// <param name="key">键名</param>
        /// <param name="value">值</param>
        public void Set<T>(string key, T value)
        {
            var data = Serialize(value);
            this.Client.Set<byte[]>(key, data);
        }

        /// <summary>
        /// 获取指定键的值
        /// </summary>
        /// <typeparam name="T">值类型</typeparam>
        /// <param name="key">键名</param>
        /// <returns></returns>
        public T Get<T>(string key)
        { 
            var data = this.Client.Get<byte[]>(key);
            return Deserialize<T>(data);
        }

        /// <summary>
        /// 移除指定键
        /// </summary>
        /// <param name="key">键名</param>
        public void Remove(string key)
        {
            this.Client.Remove(key);
        }

        static byte[] Serialize<T>(T o)
        {
            if (o == null)
                return null;

            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream())
            {
                formatter.Serialize(stream, o);
                byte[] data = stream.ToArray();
                return data;
            }
        }

        static T Deserialize<T>(byte[] data)
        {
            if (data == null || data.Length == 0)
                return default(T);

            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream(data))
            {
                T result = (T)formatter.Deserialize(stream);
                return result;
            }
        }
    }
}
